package nacgraphs;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public final class DataManager
{
    private DataReader dataReader;
    
    public DataManager()
    {
        dataReader = new DataReader();
    }
    
    public DataManager(String rootPath)
    {
        dataReader = new DataReader(rootPath);
    }

    public ArrayList<Student> getFriends(int rm)
    {
        ArrayList<Student> friends = new ArrayList<Student>();
        
        if(dataReader.getData().containsKey(rm))
        {
            Student student = dataReader.getData().get(rm);
            
            for(int friendRm : student.getFriendsRms())
            {
                if(dataReader.getData().containsKey(friendRm))
                {
                    friends.add(dataReader.getData().get(friendRm));
                }
                else
                {
                    friends.add(new Student(friendRm));
                }
            }
        }
        
        return friends;
    }
    
    public ArrayList<Student> getAllEnrolledStudents()
    {
        ArrayList<Student> students = new ArrayList<Student>();
        
        for(Map.Entry<Integer, Student> entry : dataReader.getData().entrySet())
        {
            Student value = entry.getValue();
            
            students.add(value);
        }
        
        return students;
    }
    
    public ArrayList<Student> getAllStudents()
    {
        ArrayList<Student> students = new ArrayList<Student>();
        
        for(Map.Entry<Integer, Student> entry : dataReader.getData().entrySet())
        {
            Student value = entry.getValue();
            
            if(!students.contains(value))
            {
                students.add(value);
            }
            
            for(int friendRm : value.getFriendsRms())
            {
                Student friend = dataReader.getData().get(friendRm);
                
                if(friend == null)
                {
                    friend = new Student(friendRm);
                }
                
                if(!students.contains(friend))
                {
                    students.add(friend);
                }
            }
        }
        
        return students;
    }
    
    public ArrayList<ArrayList<Student>> getTouchableStudents(int rm)
    {
        return getTouchableStudents(rm, -1);
    }
    
    public ArrayList<ArrayList<Student>> getTouchableStudents(int rm, int max)
    {   
        ArrayList<Student> studentsHistory = new ArrayList<Student>();
        HashMap<Integer, ArrayList<Student>> hashMapStudents = new HashMap<Integer, ArrayList<Student>>();
        
        getTouchableStudents(rm, -1, studentsHistory, hashMapStudents, max, 0);
        
        ArrayList<ArrayList<Student>> touchableStudents = new ArrayList<ArrayList<Student>>();
        
        Iterator iterator = hashMapStudents.entrySet().iterator();
        
        while(iterator.hasNext())
        {
            Map.Entry pairs = (Map.Entry) iterator.next();
            
            ArrayList<Student> students = (ArrayList<Student>) pairs.getValue();
            
            touchableStudents.add(students);
            
            iterator.remove();
        }
        
        return touchableStudents;
    }
    
    public ArrayList<Student> getUntouchableStudents(int rm)
    {
        ArrayList<Student> allStudents = getAllStudents();
        ArrayList<ArrayList<Student>> touchableStudents = getTouchableStudents(rm);
        
        ArrayList<Student> untouchableStudents = new ArrayList<Student>();
        
        for(Student student : allStudents)
        {
            boolean touchableStudentsContains = false;
            
            for(ArrayList<Student> students : touchableStudents)
            {
                if((touchableStudentsContains = students.contains(student)))
                {
                    break;
                }
            }
            
            if(!touchableStudentsContains && student.getRm() != rm)
            {
                untouchableStudents.add(student);
            }
        }
        
        return untouchableStudents;
    }
    
    private void getTouchableStudents(int baseRm, int currentRm, ArrayList<Student> studentsHistory, HashMap<Integer, ArrayList<Student>> hashMapStudents, int maxDeep, int currentDeep)
    {
        if(currentDeep++ < maxDeep || maxDeep == -1)
        {
            int rm = currentRm == -1? baseRm : currentRm;

            ArrayList<Student> friends = getFriends(rm);

            for(Student friend : friends)
            {
                if(friend.getRm() != baseRm)
                {
                    if(!studentsHistory.contains(friend))
                    {
                        studentsHistory.add(friend);
                        
                        if(!hashMapStudents.containsKey(currentDeep))
                        {
                            hashMapStudents.put(currentDeep, new ArrayList<Student>());
                        }
                        
                        hashMapStudents.get(currentDeep).add(friend);

                        getTouchableStudents(baseRm, friend.getRm(), studentsHistory, hashMapStudents, maxDeep, currentDeep);
                    }
                }
            }
        }
    }
}
